﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Gakita.Model.Enemies
{   /* This class handles the logic for the Giant Rabbit enemy. The Giant Rabbit walks to the right until there is 
       no more land to walk on, in which case it will make a jump. */
    class GiantRabbit
    {
        private Vector2 _bottomCenterPosition;
        private Vector2 _startPosition;
        private Vector2 _speed                      =       Vector2.Zero;
        private bool _isJumpingOrSpawning           =       true;

        public Vector2 _size                        =       new Vector2(2.8f, 4.8f);

        public GiantRabbit(Vector2 aPosition)
        {
            _bottomCenterPosition = aPosition;
            _startPosition = aPosition;
        }

        public void Update(float aElapsedTime, Level aLevel)
        {
            // If the Rabbit has reached the end of the level and is about to walk out of it, it will stop.
            if (_bottomCenterPosition.X > Level._levelWidth - _size.X / 2)
            {
                return;
            }

            Vector2 gravity = new Vector2(0,12);

            // When the rabbit is not jumping or spawning, it's not affected by gravity. When the rabbit can no longer walk further, 
            // it will check if it can perform any of two available jumps. If so, it will jump.
            if (_isJumpingOrSpawning == false)
            {
                Vector2 nextPosition = _bottomCenterPosition + _speed * aElapsedTime;

                if (GiantRabbitCantWalkFurtherInThatDirection(nextPosition, aLevel))
                {
                    if (CanDoLowJump(aLevel))
                    {
                        DoLowJump();
                    }
                    else if (CanDoHighJump(aLevel))
                    {
                        DoHighJump();
                    }
                }
                else
                {
                    _bottomCenterPosition = nextPosition;
                }
            }
            // When the rabbit is jumping or spawning it is affected by gravity. We check if the rabbit has collided with the ground,
            // and if so, we set it's state to notjumping
            else if (_isJumpingOrSpawning == true)
            {
                if (GiantRabbitHasLanded(aLevel))
                {
                    _isJumpingOrSpawning = false;
                    _setStandardSpeed();
                }
                else
                {
                    _bottomCenterPosition = _bottomCenterPosition + _speed * aElapsedTime + gravity * aElapsedTime * aElapsedTime;

                    _speed = _speed + aElapsedTime * gravity;
                }
            }
            
        }

        private void _setStandardSpeed()
        {
            _speed = new Vector2(3.20f, 0);
        }

        /* Method to check if the rabbit has landed on the ground. If it has, it's moved up so it's standing on the ground*/
        private bool GiantRabbitHasLanded(Level aLevel)
        {
            if ((int)aLevel._tiles[(int)_bottomCenterPosition.X, (int)_bottomCenterPosition.Y] > 0)
            {
                _bottomCenterPosition.Y = (int)_bottomCenterPosition.Y;
                return true;
            }
            return false;
        }

        /* Method to check if the tile in front of the rabbit is empty, if so, it can't walk further ahead */
        private bool GiantRabbitCantWalkFurtherInThatDirection(Vector2 aNextPosition, Level aLevel)
        {
            if ((int)aLevel._tiles[(int)aNextPosition.X + 1, (int)aNextPosition.Y] == 0)
            {
                return true;
            }
            return false;
        }

        /* Method to perform a high jump */
        private void DoHighJump()
        {
            // We move the rabbit up to avoid it colliding with the ground immediately
            _bottomCenterPosition.Y -= 0.01f;

            _isJumpingOrSpawning = true;
            _speed.Y = -9.0f;
        }

        /* Method to perform a lower jump */
        private void DoLowJump()
        {
            // We move the rabbit up to avoid it colliding with the ground immediately
            _bottomCenterPosition.Y -= 0.01f;

            _isJumpingOrSpawning = true;
            _speed.Y = -8f;
        }
        /* Method to check if it's possible to perform a high jump and land on a tile */
        private bool CanDoHighJump(Level aLevel)
        {
            if ((int)aLevel._tiles[(int)_bottomCenterPosition.X + 5, (int)_bottomCenterPosition.Y - 2] > 0)
            {
                return true;
            }
            return false;
        }

        /* Method to check if it's possible to perform a low jump and land on a tile */
        private bool CanDoLowJump(Level aLevel)
        {
            if ((int)aLevel._tiles[(int)_bottomCenterPosition.X + 6, (int)_bottomCenterPosition.Y] > 0)
            {
                return true;
            }
            return false;
        }

        /* Method to reset the rabbit to it's staring possition. Called when the player dies */
        public void Reset()
        {
            _bottomCenterPosition = _startPosition;
            _isJumpingOrSpawning = true;
            _speed = Vector2.Zero;
        }

        public Vector2 GetPosition()
        {
            return _bottomCenterPosition;
        }

    }
}
